home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmbase-grok-1.2 / help.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  8KB  |  257 lines

  1. /*
  2.  * print help popup on a particular topic. Help topics are identified by
  3.  * a short string that is looked up in the help file. The help file contains
  4.  * a list of button help entries; each consisting of a line "%% topic"
  5.  * followed by help text lines. Leading blanks in text lines are ignored.
  6.  * Lines beginning with '#' are ignored.
  7.  *
  8.  * To add a help text to a widget, call
  9.  *    XtAddCallback(widget, XmNhelpCallback, help_callback, "topic")
  10.  * and add "%%n topic" and the help text to the help file (n is a number
  11.  * used for extracting a user's manual, it is not used by the grok program).
  12.  *
  13.  * help_callback(parent, topic)        Print help for a topic, usually for
  14.  *                    button <parent>.
  15.  */
  16.  
  17. #include "config.h"
  18. #include <X11/Xos.h>
  19. #include <stdlib.h>
  20. #include <Xm/Xm.h>
  21. #include <Xm/DialogS.h>
  22. #include <Xm/Form.h>
  23. #include <Xm/Frame.h>
  24. #include <Xm/LabelP.h>
  25. #include <Xm/LabelG.h>
  26. #include <Xm/PushBP.h>
  27. #include <Xm/PushBG.h>
  28. #include <Xm/ToggleB.h>
  29. #include <Xm/Text.h>
  30. #include <Xm/Protocols.h>
  31. #include <X11/cursorfont.h>
  32. #include "grok.h"
  33. #include "form.h"
  34. #include "proto.h"
  35.  
  36. static void done_callback    (Widget, int, XmToggleButtonCallbackStruct *);
  37. static void context_callback (Widget, int, XmToggleButtonCallbackStruct *);
  38. static char *get_text(char *);
  39.  
  40. extern Display        *display;    /* everybody uses the same server */
  41. extern XFontStruct    *font[NFONTS];    /* fonts: FONT_* */
  42. extern XmFontList    fontlist[NFONTS];
  43. extern Pixel        color[NCOLS];    /* colors: COL_* */
  44. extern CARD         *curr_card;    /* card being displayed in main win */
  45.  
  46. static BOOL        have_shell;    /* message popup exists if TRUE */
  47. static Widget        shell;        /* popup menu shell */
  48.  
  49.  
  50. /*
  51.  * destroy the help popup. Remove it from the screen, and destroy its widgets.
  52.  */
  53.  
  54. void destroy_help_popup(void)
  55. {
  56.     if (have_shell) {
  57.         XtPopdown(shell);
  58.         XtDestroyWidget(shell);
  59.         have_shell = FALSE;
  60.     }
  61. }
  62.  
  63.  
  64.  
  65. /*
  66.  * look up the help text for <topic> and create a window containing the text.
  67.  */
  68.  
  69. /*ARGSUSED*/
  70. void help_callback(
  71.     Widget            parent,
  72.     char            *topic)
  73. {
  74.     static BOOL        have_fontlist;
  75.     static XmFontList    fontlist;
  76.     static Widget        text_w;
  77.     Widget            form, w;
  78.     Atom            closewindow;
  79.     char            *message;
  80.     Arg            args[20];
  81.     int            n;
  82.     int            nlines = 1;
  83.     char            *p;
  84.  
  85.     if (!(message = get_text(topic)))
  86.         return;
  87.     if (!strcmp(topic, "card") && curr_card && curr_card->form
  88.                         && curr_card->form->help) {
  89.         if (!(message = realloc(message, strlen(message) +
  90.                      strlen(curr_card->form->help) + 2)))
  91.             return;
  92.         strcat(message, "\n");
  93.         strcat(message, curr_card->form->help);
  94.     }
  95.     if (have_shell) {
  96.         XmTextSetString(text_w, message);
  97.         XtPopup(shell, XtGrabNone);
  98.         free(message);
  99.         return;
  100.     }
  101.     if (!have_fontlist++)
  102.         fontlist = XmFontListCreate(font[FONT_HELP], "cset");
  103.     for (nlines=0, p=message; *p; p++)
  104.         nlines += *p == '\n';
  105.     if (nlines > 30)
  106.         nlines = 30;
  107.  
  108.     n = 0;
  109.     XtSetArg(args[n], XmNdeleteResponse,    XmDO_NOTHING);        n++;
  110.     XtSetArg(args[n], XmNiconic,        False);            n++;
  111.     shell = XtAppCreateShell("Help", "Grok",
  112.             applicationShellWidgetClass, display, args, n);
  113.     set_icon(shell, 1);
  114.     form = XtCreateManagedWidget("helpform", xmFormWidgetClass,
  115.             shell, NULL, 0);
  116.     XtAddCallback(form, XmNhelpCallback,
  117.             (XtCallbackProc)help_callback, (XtPointer)"help");
  118.  
  119.                             /*-- buttons --*/
  120.     n = 0;
  121.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  122.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  123.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  124.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  125.     XtSetArg(args[n], XmNwidth,        80);            n++;
  126.     w = XtCreateManagedWidget("Dismiss", xmPushButtonWidgetClass,
  127.             form, args, n);
  128.     XtAddCallback(w, XmNactivateCallback,
  129.             (XtCallbackProc)done_callback, (XtPointer)0);
  130.     XtAddCallback(w, XmNhelpCallback,
  131.             (XtCallbackProc)help_callback, (XtPointer)"help_done");
  132.     n = 0;
  133.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  134.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  135.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  136.     XtSetArg(args[n], XmNrightWidget,    w);            n++;
  137.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  138.     XtSetArg(args[n], XmNwidth,        80);            n++;
  139.     w = XtCreateManagedWidget("Context", xmPushButtonWidgetClass,
  140.             form, args, n);
  141.     XtAddCallback(w, XmNactivateCallback,
  142.             (XtCallbackProc)context_callback, (XtPointer)0);
  143.     XtAddCallback(w, XmNhelpCallback,
  144.             (XtCallbackProc)help_callback, (XtPointer)"help_ctx");
  145.  
  146.                             /*-- text --*/
  147.     n = 0;
  148.     XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  149.     XtSetArg(args[n], XmNtopOffset,        8);            n++;
  150.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_WIDGET);    n++;
  151.     XtSetArg(args[n], XmNbottomWidget,    w);            n++;
  152.     XtSetArg(args[n], XmNbottomOffset,    16);            n++;
  153.     XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  154.     XtSetArg(args[n], XmNleftOffset,    8);            n++;
  155.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  156.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  157.     XtSetArg(args[n], XmNhighlightThickness,0);            n++;
  158.     XtSetArg(args[n], XmNeditable,        False);            n++;
  159.     XtSetArg(args[n], XmNeditMode,        XmMULTI_LINE_EDIT);    n++;
  160.     XtSetArg(args[n], XmNcolumns,        60);            n++;
  161.     XtSetArg(args[n], XmNrows,        nlines+1);        n++;
  162.     XtSetArg(args[n], XmNfontList,        fontlist);        n++;
  163.     XtSetArg(args[n], XmNscrollVertical,    True);            n++;
  164.     XtSetArg(args[n], XmNpendingDelete,    False);            n++;
  165.     text_w = w = XmCreateScrolledText(form, "text", args, n);
  166.     XmTextSetString(w, message);
  167.     XtVaSetValues(w, XmNbackground,    color[COL_SHEET], NULL);
  168.     XtManageChild(w);
  169.     XtAddCallback(w, XmNhelpCallback,
  170.             (XtCallbackProc)help_callback, (XtPointer)"help");
  171.     XtPopup(shell, XtGrabNone);
  172.     closewindow = XmInternAtom(display, "WM_DELETE_WINDOW", False);
  173.     XmAddWMProtocolCallback(shell, closewindow,
  174.             (XtCallbackProc)done_callback, (XtPointer)shell);
  175.     have_shell = TRUE;
  176.     free(message);
  177. }
  178.  
  179.  
  180. /*ARGSUSED*/
  181. static void done_callback(
  182.     Widget                widget,
  183.     int                item,
  184.     XmToggleButtonCallbackStruct    *data)
  185. {
  186.     destroy_help_popup();
  187. }
  188.  
  189.  
  190. /*ARGSUSED*/
  191. static void context_callback(
  192.     Widget                widget,
  193.     int                item,
  194.     XmToggleButtonCallbackStruct    *data)
  195. {
  196.     Widget w;
  197.     Cursor cursor = XCreateFontCursor(display, XC_question_arrow);
  198.     if (w = XmTrackingLocate(shell, cursor, False)) {
  199.         data->reason = XmCR_HELP;
  200.         XtCallCallbacks(w, XmNhelpCallback, &data);
  201.     }
  202.     XFreeCursor(display, cursor);
  203. }
  204.  
  205.  
  206. /*ARGSUSED*/
  207. static char *get_text(
  208.     char            *topic)
  209. {
  210.     FILE            *fp;        /* help file */
  211.     char            line[1024];    /* line buffer (and filename)*/
  212.     char            *text;        /* text buffer */
  213.     int            textsize;    /* size of text buffer */
  214.     int            textlen = 0;    /* # of chars in text buffer */
  215.     int            n;        /* for stripping trailing \n */
  216.     register char        *p;
  217.  
  218.     if (!(text = (char *)malloc(textsize = 4096)))
  219.         return(0);
  220.     *text = 0;
  221.     if (!find_file(line, HELP_FN, FALSE) || !(fp = fopen(line, "r"))) {
  222.         sprintf(text, "Sorry, no help available,\n%s not found",
  223.                                 HELP_FN);
  224.         return(text);
  225.     }
  226.     for (;;) {                    /* find topic */
  227.         if (!fgets(line, 1024, fp)) {
  228.             strcpy(text, "Sorry, no help available on this topic");
  229.             return(text);
  230.         }
  231.         if (line[0] != '%' || line[1] != '%')
  232.             continue;
  233.         line[strlen(line)-1] = 0; /* strip \n */
  234.         for (p=line+2; *p >= '0' && *p <= '9'; p++);
  235.         for (; *p == ' ' || *p == '\t'; p++);
  236.         if (*p && *p != '\n' && !strcmp(p, topic))
  237.             break;
  238.     }
  239.     for (;;) {                    /* read text */
  240.         if (!fgets(line, 1024, fp))
  241.             break;
  242.         if (line[0] == '#')
  243.             continue;
  244.         if (line[0] == '%' && line[1] == '%')
  245.             return(text);
  246.         p = line[0] == '\t' ? line+1 : line;
  247.         if (textlen + strlen(p) + 1 > textsize)
  248.             if (!(text = (char *)realloc(text, textsize += 4096)))
  249.                 break;
  250.         strcat(text, p);
  251.         textlen += strlen(p);
  252.     }
  253.     for (n=strlen(text); n && text[n-1] == '\n'; n--)
  254.         text[n-1] = 0;
  255.     return(text);
  256. }
  257.